Skip to content

feat(devx): pin the ported guard-main-checkout self-test, and stop --resync rewriting governed files - #7954

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-7263-port-pin-hooks-and-governed-resync-guard
Sep 6, 2026
Merged

feat(devx): pin the ported guard-main-checkout self-test, and stop --resync rewriting governed files#7954
baozhoutao merged 1 commit into
mainfrom
claude/issue-7263-port-pin-hooks-and-governed-resync-guard

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #7263

scripts/upstream-port-pin.json covered only scripts/, so the verbatim cross-repo ports under .claude/hooks/** — this repo's densest concentration of copies from one upstream, and the directory whose drift history is four separate human catches (#5459, #5712, #5789, #6042) — had no drift gate. Two changes, in the order they have to happen.

1. --resync refuses to rewrite governed surface

Registering a file EDITS nothing; --resync REWRITES one in place, from another repository's bytes. Only the second is a governed-surface act. --resync now refuses any ported path on the governed surface unless --rewrite-governed-file is passed, naming the path, the surface it matched and the flag. The governed set is read from governedPathsIn in scripts/check-governed-queue-guard.mjs — the repo's own definition, reused rather than re-listed, so the two cannot disagree.

The CHECK path is untouched. A drifted governed port reds with no flag and no exemption; two self-test rows pin exactly that, because a gate that went quiet on the surface with the worst drift history would be this mechanism inverted.

Measured on this branch, all three legs:

$ node scripts/check-upstream-port-parity.mjs --resync /tmp/up-hook.sh --ref bf10debd5… \
    --path .claude/hooks/guard-main-checkout.selftest.sh                     # EXIT 2
⛔ refusing to rewrite .claude/hooks/guard-main-checkout.selftest.sh: it is GOVERNED SURFACE
   (.claude/** — the agent instruction tree (skills, hooks, settings)), which this repository
   merges by human review.
  • To do it anyway — as the human doing that merge — pass --rewrite-governed-file.
  • Registering this file in the pin is NOT affected: checking is not writing, and a
    drifted governed port reds this gate with no flag and no exemption.
$ git status --porcelain      # empty — the refusal is proved by state, not by the exit code

$ … --rewrite-governed-file                                                  # EXIT 0
.claude/hooks/guard-main-checkout.selftest.sh is GOVERNED SURFACE (…) and --rewrite-governed-file
was passed: rewriting it in place.
✓ re-synced … (14 divergence(s) re-applied) and bumped the pin.
    blob before 4844703e2a72bb… → after 4844703e2a72bb…   (same ref in, byte-identical out)

$ … --resync /tmp/up-invoked-as.mjs --path scripts/invoked-as.mjs            # EXIT 0
✓ re-synced scripts/invoked-as.mjs … — no refusal: a non-governed path is unchanged.

2. The first .claude/** entry, and what re-deriving it actually measured

⚠️ The card's readiness measurement no longer holds, and this is the delta it asked for. #7263 measured this file at "exactly 4 declared divergences, all comment / echo-label text, no executable line differs", at upstream d63c8a2. Re-derived today:

So the entry is registered with 14 declared divergences, not 4, and 12 of them cover executable text. Each carries its one-sentence why; twelve name #7686, two name the port itself (the provenance header, and the KNOWN HOLE re-pointing at this repo's own #7259 with upstream's number kept as a cross-reference). The gate's green line is exactly true and says what it verified:

✓ .claude/hooks/guard-main-checkout.selftest.sh: byte-identical to
  objectstack-ai/objectstack@bf10debd5:.claude/hooks/guard-main-checkout.selftest.sh
  modulo 14 declared divergence(s).
✓ check-upstream-port-parity: 3 ported file(s) match objectstack-ai/objectstack@bf10debd5
  modulo their declared divergences.

⚠️ What that row does NOT say: that this hook matches upstream today. Against upstream main (a4816a79d) the same file still differs by 102 lines (40 executable), two of them live and already tracked — the substring worktree hole (#7259, and PR #7749 is in flight on it) and the escape-hatch remedy sentence (#7775). The pin's single upstream.ref cannot see either. That, plus the drift table for the other seven hooks, is filed as #7953.

Reverse verification

Mutated on disk, gate read, restored with git checkout HEAD -- PATH, restore proved by blob hash (4844703e2a72bb…) and an empty git diff HEAD each time. All three drift directions reached:

mutation direction reached gate
a comment byte inside a declared region (87 passed88 passed) names the divergence ported-from-provenance-header EXIT 1
an echo heading inside a declared region (#7259#7258) names the divergence hole-heading-repointed EXIT 1
an assertion line outside every declared region (y.tsz.ts) digest mismatch, "the difference is OUTSIDE all of them" EXIT 1

⚠️ Two honest notes on this table. The first mutation was chosen expecting the digest-mismatch direction and landed inside a declared region instead — the observed direction is reported, not the predicted one. And a fourth attempt produced no diff at all (a perl one-liner whose escaping silently matched nothing, exit 0); it was caught by counting the deleted and injected text on disk rather than by trusting the editor's exit code, and re-run.

Wiring: one assertion re-scoped, one added

upstream-port-parity-wiring.test.ts asserted pinned ⊆ half-state-patrol.paths. That silently encoded "the ledger only ever pins the sweeper's unit" — true of the two entries that existed, not a property of the ledger — and it reds on the first entry outside scripts/. It is re-scoped to the patrol's own unit in both directions, and the claim that matters for entries beyond it is now asserted directly: no pinned file falls inside lint.yml's ignore set, so the pull request that drifts a pinned file is never the one on which the gate does not run. That test carries a control leg — each ignore glob must recognise a file it exists to ignore — because the first version of its glob matcher matched nothing and passed.

Serial note

⚠️ PR #7749 (draft, another seat) edits this same self-test's KNOWN HOLE section. This entry is derived against main as of f10e49f36, deliberately not against that branch; when #7749 lands, divergences hole-heading-repointed, hole-crossref-repointed and their neighbours need re-deriving, and the gate will say so loudly rather than quietly (expected its ported text exactly once, found 0).

Gates

gate verdict line
check-upstream-port-parity ✓ … 3 ported file(s) match … (was 2)
… --self-test ✓ … 49 cases pass (was 37)
scripts/__tests__ (3 suites) Test Files 3 passed (3) · Tests 46 passed (46)
pnpm type-check:scripts exit 0
pnpm lint:root ✖ 32 problems (0 errors, 32 warnings); the three changed files re-linted alone: 0 errors, 0 warnings
pnpm check:control-bytes ✅ OK (scanned 6410 tracked text file(s))
pnpm check:governed-queue-guard OK … 132 cases pass
check-governed-queue-guard --test (the 3 changed paths) ✅ NOT GOVERNED — 3 path(s) checked against 5 governed surface(s); none matched.
check-changeset-presence ✅ No source or published contract of a released package changed in this range

Run at 4263ff3f4. No file under .claude/** is edited by this pull request — the ported file is registered, not touched.


Generated by Claude Code

…resync rewriting governed files

`scripts/upstream-port-pin.json` covered only `scripts/`, so the verbatim
cross-repo ports under `.claude/hooks/**` — this repo's densest concentration of
copies from the same upstream, and the one directory whose drift history is four
separate human catches (#5459, #5712, #5789, #6042) — had no drift gate at all.

Two changes, in the order they have to happen:

1. `--resync` now REFUSES to rewrite a ported path on the governed surface
   unless `--rewrite-governed-file` is passed, naming the path, the surface it
   matched and the flag. The governed set is read from
   `check-governed-queue-guard.mjs` rather than re-listed. The CHECK path is
   untouched: a drifted governed port reds with no flag and no exemption.
2. `.claude/hooks/guard-main-checkout.selftest.sh` is registered against the
   upstream blob the pin already names, with 14 declared divergences and a
   one-sentence `why` each.

The wiring test's `pinned ⊆ patrol.paths` assertion silently encoded "the ledger
only pins the sweeper's unit". It is re-scoped to the patrol's own unit, and the
claim that matters for entries outside it is asserted directly: no pinned file
falls inside `lint.yml`'s ignore set, so the PR that drifts one is never the PR
on which the gate does not run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013uAaxiwgYDybsTNV9xwa1M
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants